# -*- coding: utf-8 -*-
from typing import List, Optional

import requests
from fastapi import APIRouter, Depends, HTTPException, Request, Response
from sqlalchemy.orm import Session
from starlette import status
from fastapi.templating import Jinja2Templates
from starlette.background import BackgroundTasks
from pydantic import HttpUrl

from coronavirus import crud, schemas
from coronavirus.database import engine, Base, SessionLocal
from coronavirus.models import City, Data

coronavirus_app = APIRouter()

templates = Jinja2Templates(directory='./coronavirus/templates')

Base.metadata.create_all(bind=engine)


# 获取数据库连接
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


@coronavirus_app.post('/create_city', response_model=schemas.ReadCity)
def create_city(city: schemas.CreateCity, db: Session = Depends(get_db)):
    db_city = crud.get_city_by_name(db=db, name=city.province)
    if db_city:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="City already registered")
    city = crud.create_city(db=db, city=city)
    return city


@coronavirus_app.get('/get_city/{city}', response_model=schemas.ReadCity)
def get_city(city: str, db: Session = Depends(get_db)):
    db_city = crud.get_city_by_name(db=db, name=city)
    if db_city is None:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="City not found")
    return db_city


@coronavirus_app.get('/get_cities', response_model=List[schemas.ReadCity])
def get_cities(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
    db_cities = crud.get_cities(db=db, skip=skip, limit=limit)
    return db_cities


@coronavirus_app.post('/create_data', response_model=schemas.ReadData)
def create_data(city: str, data: schemas.CreateData, db: Session = Depends(get_db)):
    db_city = crud.get_city_by_name(db=db, name=city)
    data = crud.create_city_data(db=db, data=data, city_id=db_city.id)
    return data


@coronavirus_app.get('/get_data')
def get_data(skip: int = 0, limit: int = 10, city: str = None, db: Session = Depends(get_db)):
    db_data = crud.get_data(db=db, city=city, skip=skip, limit=limit)
    return db_data


def bg_task(url: HttpUrl, db: Session):
    """
    不要在后台任务的参数中导入这样的依赖  例如：  db: Session = Depends(get_db)
    :param url:
    :param db:
    :return:
    """
    city_data = requests.get(url=f"{url}?source=jhu&country_code=CN&timelines=false")
    if city_data.status_code == 200:
        # 同步前，先清空老数据
        db.query(City).delete()
        for location in city_data.json()["locations"]:
            city = {
                "country_code": location["country_code"],
                "country": location["country"],
                "country_population": location["country_population"],
                "province": location["province"]
            }
            crud.create_city(db=db, city=schemas.CreateCity(**city))

    coronavirus_data = requests.get(url=f"{url}?source=jhu&country_code=CN&timelines=true")
    if coronavirus_data.status_code == 200:
        db.query(Data).delete()
        for city in coronavirus_data.json()["locations"]:
            db_city = crud.get_city_by_name(db=db, name=city["province"])
            for date, confirmed in city["timelines"]["confirmed"]["timeline"].items():
                data = {
                    "date": date.split("T")[0],
                    "confirmed": confirmed,
                    "death": city["timelines"]["deaths"]["timeline"][date],
                    "recovered": 0
                }
                crud.create_city_data(db=db, data=schemas.CreateData(**data), city_id=db_city.id)


# sync_data_url
@coronavirus_app.get('/sync_coronavirus_data/jhu')
def sync_coronavirus_data(background_tasks: BackgroundTasks, db: Session = Depends(get_db)):
    """
    从Johns Hopkins University同步COVID-19数据
    :param background_tasks:
    :param db:
    :return:
    """
    background_tasks.add_task(bg_task, "https://coronavirus-tracker-api.herokuapp.com/v2/locations", db)
    return {"message": "正在同步数据"}


# 前端使用框架是 https://semantic-ui.com/
@coronavirus_app.get('/')
def coronavirus(request: Request, city: str = None, skip: int = 0, limit: int = 10,  db: Session = Depends(get_db)):
    data = crud.get_data(db=db, city=city, skip=skip, limit=limit)
    return templates.TemplateResponse("home.html", {
        "request": request,
        "data": data,
        "sync_data_url": "/coronavirus_app/sync_coronavirus_data/jhu"
    })



